package com.wn.sk.product.job;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.wn.sk.product.contants.PromotionStatus;
import com.wn.sk.product.contants.RedisKey;
import com.wn.sk.product.entity.PromotionSeckill;
import com.wn.sk.product.entity.vo.PromotionProductVo;
import com.wn.sk.product.mapper.ProductMapper;
import com.wn.sk.product.mapper.PromotionSeckillMapper;
import com.wn.sk.product.service.IProductService;
import com.wn.sk.product.service.IPromotionSeckillService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author yellow Docter
 * @date 2022 -11-08
 * @desc
 */
@Component
@Slf4j
public class SeckillVoJob {

    @Autowired
    private IProductService productService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private IPromotionSeckillService promotionSeckillService;

    /**
     * 9点钟进行活动
     * 8:58 数据预热 添加到redis中
     * 为了方便测试 5s执行一次
     * <p>
     * 业务实现：
     * 1、查询数据
     * 2、把数据存储到redis中
     * 3、修改数据中商品状态 (0改成 1 活动一开始 )
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void execute() throws JsonProcessingException {

        //查收数据库 ( 活动为开始的状态 )
        List<PromotionProductVo> voList = productMapper.findPromotionProduct(PromotionStatus.UN_START);

        System.out.println("voList = " + voList);

        if (!CollectionUtils.isEmpty(voList)) {
            //把数据存储到redis中
            redisTemplate.opsForList().leftPushAll(RedisKey.PRODUCT_SK_LIST, voList);
            log.info("把数据存储到redis中 ");


            //初始化 秒杀互动的库存
            initStock(voList);

            //修改数据库中的 商品的状态

//           for (PromotionProductVo promotionProductVo : voList) {
//               Integer promotionId = promotionProductVo.getPromotionId();
//               PromotionSeckill promotionSeckill = new PromotionSeckill();
//               promotionSeckill.setId(promotionId);
//               promotionSeckill.setStatus(PromotionStatus.START);  // 把状态修改成  活动已开始
//               promotionSeckillService.updateById(promotionSeckill);
//           }

            //一个个的修改
            //拿到秒杀商品的 id 通过id修改

            //修改操作
//           voList.stream().forEach(vo->{
//               Integer promotionId = vo.getPromotionId();
//               PromotionSeckill promotionSeckill = new PromotionSeckill();
//               promotionSeckill.setId(promotionId);
//               promotionSeckill.setStatus(PromotionStatus.START);  // 把状态修改成  活动已开始
//               promotionSeckillService.updateById(promotionSeckill);
//           });

            List<Integer> idList =
                    voList.stream() //拿到流的操作
                            .map(PromotionProductVo::getPromotionId) //把对象转成  秒杀商品ID
                            .collect(Collectors.toList());          //收集     把 id组成一个集合

            //update set status = 1 where id in (1,2,3);
            //添加修改

//            QueryWrapper<PromotionSeckill> queryWrapper = new QueryWrapper<>();
//
//            UpdateWrapper<PromotionSeckill> wrapper = new UpdateWrapper<>();
//            wrapper.in("id", idList);               //修改的条件
//            wrapper.set("status",PromotionStatus.START);    //状态修改
//
//            promotionSeckillService.update(wrapper);

            //mp的条件操作 支持lambda表达式
            // Wrappers  条件构造工具类

            LambdaUpdateWrapper<PromotionSeckill> seckillLambdaUpdateWrapper =
                    Wrappers.lambdaUpdate(PromotionSeckill.class);  //修改lambda表达式的 Wrapper
            seckillLambdaUpdateWrapper.in(PromotionSeckill::getId,idList)  // LambdaUpdateWrapper 内部的方法都需要给方法的引用 获取字段
                    .set(PromotionSeckill::getStatus,PromotionStatus.START);

            promotionSeckillService.update(seckillLambdaUpdateWrapper);

        }
    }

    /**
     * 初始化库存
     *
     * 设计数据的类型是list ：
     * sk:1    [871,871,871]
     * sk:2    [872,872,872,872,872]
     *
     * @param voList
     */
    private void initStock(List<PromotionProductVo> voList) {

        voList.stream().forEach(vo->{

            //拿到 秒杀活动id
            Integer promotionId = vo.getPromotionId();
            Integer productId = vo.getProductId();
            //库存
            Long stock = vo.getStock();
            String key = RedisKey.PRODUCT_SK_STOCK + ":" + promotionId;
            for (int i = 0; i < stock; i++) {
                redisTemplate.opsForList().leftPush(key,productId);
            }

            log.info("秒杀互动库存 初始化 已完成....");
        });

    }
}
